package com.casic.aspect;

import com.casic.dao.IotDeviceDao;
import com.casic.dao.IotIotDao;
import com.casic.dto.ParamDTO;
import com.casic.entity.IotDevice;
import com.casic.entity.IotIot;
import com.casic.util.R;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Map;

/**
 * @author xudezhi
 * @title: AuthAspect
 * @projectName iot-platform
 * @description: TODO
 * @date 2021/4/139:17:58
 */
@Slf4j
@Aspect
@Component
public class AuthAspect {

    @Autowired
    IotIotDao iotDao;

    /**
     * 设备的dao
     */
    @Autowired
    private IotDeviceDao iotDeviceDao;

    @Pointcut("@annotation(com.casic.aspect.annotation.Auth)")
    public void dataFilterCut() {

    }

    @Around("dataFilterCut()")
    public Object dataFilter(ProceedingJoinPoint point){
        log.info("进行AccessKey判断");
        try {
            if (point.getArgs() == null) {
                return R.error("接受参数对象异常");
            }

            Object params = point.getArgs()[0];
            if (params == null || !(params instanceof ParamDTO)) {
                return R.error("接受参数对象异常");
            }
            ParamDTO dto = (ParamDTO) params;


            //1.校验参数完整性
            //2.校验设备网关状态信息
            //3.校验采集时间的毫米级别
            Boolean checkResult = new Boolean(true);
            /**
             * 校验
             */
            String msg = "";
            if (point.getSignature().getName().equals("dataAcquire") || point.getSignature().getName().equals("data")) {
                msg = checkResult(checkResult, dto, DataType.data);
            } else {
                msg = checkResult(checkResult, dto, DataType.state);
            }
            /**
             * 校验不通过
             */
            if (!"校验通过".equals(msg)) {
                return R.error(msg);
            }
            try {
                return point.proceed();
            } catch (Throwable throwable) {
                return R.error(throwable.getMessage());
            }
        }catch (Exception e){
            return R.error(e.getMessage());
        }
    }

    /**
     * 类型枚举
     */
    enum DataType{
        data,state
    }
    /**
     *
     * @param checkResult
     * @param dto
     * @return
     */
    private String checkResult(Boolean checkResult, ParamDTO dto,DataType dataType) throws Exception {
        String message="校验通过";

        //网关为空
        if(StringUtils.isEmpty(dto.getIot())){
            checkResult=Boolean.FALSE;
            message="网关ID不能为空!";
            return message;
        }
        //accessKey不能为空
        if(StringUtils.isEmpty(dto.getAccessKey())){
            checkResult=Boolean.FALSE;
            message="accessKey不能为空!";
            return message;
        }

        /**
         * 根据网关id查询网关信息
         */
        IotIot iotIot =iotDao.selectByPrimaryKey(Long.valueOf(dto.getIot()));
        if (iotIot==null||!"0".equals(iotIot.getIsdelete())){
            checkResult=Boolean.FALSE;
            message="网关不存在或者已删除!";
            return message;
        }
        /**
         * 判断网关和accessKey是否对应
         */
        if(!dto.getAccessKey().equals(iotIot.getAccesskey())){
            checkResult=Boolean.FALSE;
            message="网关AccessKey错误!";
            return message;
        }

        //判断校验的是数据采集还是状态采集
        if(dataType==DataType.data){
            //数据采集
            //equipment不能为空
            if("".equals(dto.getEquipment().trim())){
                checkResult=Boolean.FALSE;
                message="设备ID不能为空!";
                return message;
            }

            /**
             * 查询设备信息
             */
            IotDevice device=iotDeviceDao.selectByPrimaryKey(dto.getEquipment());
            if(device==null||!"0".equals(device.getIsdelete())||!"1".equals(device.getStatus())){
                checkResult=Boolean.FALSE;
                message="设备不存在或者状态处于已禁用/已删除!";
                return message;
            }
            /**
             * 判断设备绑定的网关和本次传入的id是否一致
             */
            if(device.getIotid()==null||!dto.getIot().equals(String.valueOf(device.getIotid()))){
                checkResult=Boolean.FALSE;
                message="设备未绑定网关或者跟本次提交信息网关不一致!";
                return message;
            }

            /**
             * 采集点数据判断
             */
            List<Map<String, Object>> dataList = dto.getData();// 采集点数据
            if(dataList==null||dataList.size()==0){
                checkResult=Boolean.FALSE;
                message="采集信息不能为空!";
                return message;
            }

            /**
             * 查询采集点名称列表
             */
            List<String> keyNameList=iotDeviceDao.getKeyNamesById(dto.getEquipment());
            if (keyNameList==null||keyNameList.size()==0){
                checkResult=Boolean.FALSE;
                message="设备未配置采集点信息!";
                return message;
            }

            /**
             * 判断key是否存在
             */
            for (Map<String, Object> map : dataList) {
                if(!map.containsKey("k")){
                    checkResult=Boolean.FALSE;
                    message="上传采集点信息不能为空!";
                    break;
                }
                /**
                 * 判断采集点是否包含在设备的采集点中
                 */
                String  keyName=map.get("k").toString();
                if(!keyNameList.contains(keyName)){
                    checkResult=Boolean.FALSE;
                    message="采集点信息错误!";
                    break;
                }
                //判断采集点如果是状态
                if(keyName.equals("state")){
                    //获取状态值
                    String value = map.get("v").toString();
                    if(!"1000".equals(value)&&!"2000".equals(value)&&!"3000".equals(value)&&!"4000".equals(value)){
                        checkResult=Boolean.FALSE;
                        message="状态值不在正确范围内!";
                        break;
                    }
                }

                //校验t
                if(!map.containsKey("t")){
                    checkResult=Boolean.FALSE;
                    message="采集点时间戳不能为空!";
                    break;
                }else{
                    String t=map.get("t").toString();
                    if(t.length()!=13){
                        checkResult=Boolean.FALSE;
                        message="采集点时间戳需要毫秒级别长度!";
                        break;
                    }
                }

            }
            /**
             * 判断上一步赋值成了false
             */
            if(checkResult==Boolean.FALSE){
                return message;
            }


        }else if(dataType==DataType.state){
            //状态采集

            /**
             * 采集点数据判断
             */
            List<Map<String, Object>> dataList = dto.getData();// 采集点数据
            if(dataList==null||dataList.size()==0){
                checkResult=Boolean.FALSE;
                message="状态采集信息不能为空!";
                return message;
            }
            /**
             * 判断key是否存在
             */
            for (Map<String, Object> map : dataList) {
                String equipment="";
                if(map.containsKey("equipment")){
                    equipment = map.get("equipment").toString();
                }else{
                    checkResult=Boolean.FALSE;
                    message="设备ID不能为空!";
                    break;
                }

                String value="";
                /**
                 * 判断采集点包含问题
                 */
                if(!map.containsKey("v")){
                    checkResult=Boolean.FALSE;
                    message="状态值缺失!";
                    break;
                }
                //获取状态值
                value = map.get("v").toString();
                if(!"1000".equals(value)&&!"2000".equals(value)&&!"3000".equals(value)&&!"4000".equals(value)){
                    checkResult=Boolean.FALSE;
                    message="状态值不在正确范围内!";
                    break;
                }

                //校验t
                if(!map.containsKey("t")){
                    checkResult=Boolean.FALSE;
                    message="采集点时间戳不能为空!";
                    break;
                }else{
                    String t=map.get("t").toString();
                    if(t.length()!=13){
                        checkResult=Boolean.FALSE;
                        message="采集点时间戳需要毫秒级别长度!";
                        break;
                    }
                }
            }

            /**
             * 判断上一步赋值成了false
             */
            if(checkResult==Boolean.FALSE){
                return message;
            }
        }


        return message;
    }

}
